import React, {
  ReactElement,
  useState,
  useEffect,
  useContext,
  useRef,
  useMemo
} from 'react';
import {
  View,
  PanResponder,
  GestureResponderEvent,
  Image,
  Text
} from 'react-native';
import SystemSetting from 'react-native-system-setting';

import styles from './style';
import { phonePx } from '../../../../util/adapt';
import { getScreenInfo, ScreenOrientation } from '../../../../util/screen';
import { systemUtil } from '../../../../util/native';
import { DEBUG, isIOS } from '../../../../constant';
import { Store } from '../../reducer';
import { ClassRoomType, PPTType, ShowToastType } from '../../constant';
import { computeTime } from '../../func';
import {
  changeBarStatus,
  onPressNextRound,
  seekWithTime,
  setClassRoomChangeTime,
  setShowToastType
} from '../../actions';
import { brightness, dark, mute, volume } from '../../../../constant/resource';
import Button from '../../../../components/Button';
import { getClassRoomCurrentTime } from '../../store/classRoomCurrentTime';

const { width, height } = getScreenInfo({
  screenOrientation: ScreenOrientation.Landscape
});

enum Area {
  Unknown,
  Left,
  Right
}

enum MoveDirection {
  Unknown,
  Vertical,
  Horizontal
}

let localVolumeValue = 0;
let localBrightnessValue = 0;
let onPanResponderStartPageXRealTime = 0;
let timer: NodeJS.Timer | null;

let onPanResponderStartPageY = 0; // 当前Y轴距离
let onPanResponderStartPageX = 0; // 当前X轴距离
let moveArea = Area.Unknown; // 初始滑动区域
let moveDirection = MoveDirection.Unknown; // 初始滑动方向

export default (): ReactElement => {
  const { state } = useContext(Store);
  const {
    type,
    classRoomTotalTime,
    currentPPT,
    classRoomChangeTime,
    showBar,
    showToastType,
    showPrepare
  } = state;
  const [brightnessValue, setBrightnessValue] = useState<number>(0);
  const [volumeValue, setVolumeValue] = useState<number>(0);

  const view = useRef<View>(null);

  const clearTimer = (): void => {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
  };

  useEffect((): (() => void) => {
    SystemSetting.getVolume().then((v: number): void => {
      localVolumeValue = v;
      setVolumeValue(v);
    });

    SystemSetting.getAppBrightness().then((b: number): void => {
      localBrightnessValue = b;
      setBrightnessValue(b);
    });

    const volumeListener = SystemSetting.addVolumeListener(
      (data: any): void => {
        const v = data.value;

        if (v === localVolumeValue) return;

        if (moveDirection !== MoveDirection.Vertical) {
          localVolumeValue = v;
        }
        setVolumeValue(v);
        setShowToastType(ShowToastType.Volume);

        clearTimer();

        timer = setTimeout((): void => {
          setShowToastType(ShowToastType.Unknown);
        }, 1000);
      }
    );

    systemUtil.hideVolumeView(true);

    return (): void => {
      systemUtil.hideVolumeView(false);
      SystemSetting.removeVolumeListener(volumeListener);
      clearTimer();
    };
  }, []);

  useEffect((): void => {
    if (currentPPT.type === PPTType.Problem || showPrepare) {
      systemUtil.hideVolumeView(false);
    } else {
      systemUtil.hideVolumeView(true);
    }
  }, [currentPPT.type, showPrepare]);

  useEffect((): void => {
    if (view && view.current) {
      if (
        classRoomChangeTime > -1 &&
        showToastType === ShowToastType.PlayProgress
      ) {
        view.current.setNativeProps({
          style: styles.background
        });
      } else {
        view.current.setNativeProps({
          style: { backgroundColor: 'transparent' }
        });
      }
    }
  });

  const changeBrightnessValue = (value: number): void => {
    let res = localBrightnessValue + value;
    if (res < 0) {
      res = 0;
    }
    if (res > 1) {
      res = 1;
    }

    SystemSetting.setAppBrightness(res);
    setBrightnessValue(res);
    if (showToastType !== ShowToastType.Brightness) {
      setShowToastType(ShowToastType.Brightness);
    }
  };

  const changeVolumeValue = (value: number): void => {
    let res = localVolumeValue + value;
    if (res < 0) {
      res = 0;
    }
    if (res > 1) {
      res = 1;
    }

    SystemSetting.setVolume(res, { showUI: isIOS });

    if (isIOS) return;
    setVolumeValue(res);
    if (showToastType !== ShowToastType.Volume) {
      setShowToastType(ShowToastType.Volume);
    }
  };

  const changePlayProgressValue = (value: number): void => {
    if (showToastType !== ShowToastType.PlayProgress) {
      setShowToastType(ShowToastType.PlayProgress);
    }

    const classRoomCurrentTime = getClassRoomCurrentTime();
    let moveProgressTime =
      classRoomChangeTime > -1 ? classRoomChangeTime : classRoomCurrentTime;
    let step = 1;
    if (Math.abs(value) > 1) {
      step = Math.abs(value) * 2;
    }
    if (value > 0) {
      moveProgressTime += step * 1000;
    } else {
      moveProgressTime -= step * 1000;
    }
    if (moveProgressTime > classRoomTotalTime) {
      moveProgressTime = classRoomTotalTime;
    } else if (moveProgressTime < 0) {
      moveProgressTime = 0;
    }

    setClassRoomChangeTime(moveProgressTime);
  };

  const responder = PanResponder.create({
    onStartShouldSetPanResponder: (): boolean => true,
    onStartShouldSetPanResponderCapture: (): boolean => true,
    onMoveShouldSetPanResponder: (): boolean => true,
    onMoveShouldSetPanResponderCapture: (): boolean => true,
    onPanResponderEnd: (): void => {
      moveArea = Area.Unknown;
      if (moveDirection === MoveDirection.Unknown) {
        changeBarStatus(!showBar);
        return;
      }

      moveDirection = MoveDirection.Unknown;

      if (showToastType === ShowToastType.Volume) {
        localVolumeValue = volumeValue;
      } else if (showToastType === ShowToastType.Brightness) {
        localBrightnessValue = brightnessValue;
      } else if (showToastType === ShowToastType.PlayProgress) {
        seekWithTime(Math.floor(classRoomChangeTime));
      }
      clearTimer();
      timer = setTimeout((): void => {
        setShowToastType(ShowToastType.Unknown);
      }, 1000);
    },
    onPanResponderGrant: (evt): void => {
      onPanResponderStartPageY = evt.nativeEvent.pageY;
      onPanResponderStartPageX = evt.nativeEvent.pageX;
      onPanResponderStartPageXRealTime = evt.nativeEvent.pageX;
      if (onPanResponderStartPageX > width / 2) {
        moveArea = Area.Right;
      } else {
        moveArea = Area.Left;
      }
    },
    onPanResponderMove: (evt: GestureResponderEvent): void => {
      if (
        !(
          Math.abs(onPanResponderStartPageY - evt.nativeEvent.pageY) > 2 ||
          Math.abs(onPanResponderStartPageX - evt.nativeEvent.pageX) > 2
        )
      ) {
        return;
      }
      if (moveDirection === MoveDirection.Unknown) {
        clearTimer();

        if (
          Math.abs(onPanResponderStartPageY - evt.nativeEvent.pageY) +
            (isIOS ? 3 : 0) >
          Math.abs(onPanResponderStartPageX - evt.nativeEvent.pageX)
        ) {
          moveDirection = MoveDirection.Vertical;
        } else {
          moveDirection = MoveDirection.Horizontal;
          changeBarStatus(true);
        }
      }

      if (moveDirection === MoveDirection.Vertical) {
        const scrollY = onPanResponderStartPageY - evt.nativeEvent.pageY;
        const scale = Number((scrollY / height).toFixed(2));
        if (moveArea === Area.Left) {
          changeBrightnessValue(scale);
        } else if (moveArea === Area.Right) {
          changeVolumeValue(scale);
        }
      } else if (
        moveDirection === MoveDirection.Horizontal &&
        type === ClassRoomType.Vod
      ) {
        const scrollX =
          evt.nativeEvent.pageX - onPanResponderStartPageXRealTime;
        if (Math.abs(scrollX) > 0.5) {
          onPanResponderStartPageXRealTime = evt.nativeEvent.pageX;
          changePlayProgressValue(scrollX);
        }
      }
    }
  });

  return useMemo((): ReactElement => {
    if (currentPPT.type === PPTType.Problem || showPrepare) {
      return <View />;
    }
    return (
      <View style={styles.container} ref={view}>
        <View {...responder.panHandlers} style={styles.content} />

        <View style={styles.model} />

        {showToastType === ShowToastType.Volume && (
          <View style={styles.progressContent}>
            <Image
              source={volumeValue > 0 ? volume : mute}
              style={styles.volumeIcon}
              resizeMode="contain"
            />
            <View style={styles.lineContent}>
              <View
                style={[styles.progress, { width: volumeValue * phonePx(156) }]}
              />
            </View>
          </View>
        )}

        {showToastType === ShowToastType.Brightness && (
          <View style={styles.progressContent}>
            <Image
              source={brightnessValue > 0 ? brightness : dark}
              style={styles.volumeIcon}
              resizeMode="contain"
            />
            <View style={styles.lineContent}>
              <View
                style={[
                  styles.progress,
                  { width: brightnessValue * phonePx(156) }
                ]}
              />
            </View>
          </View>
        )}

        {classRoomChangeTime > -1 &&
          showToastType === ShowToastType.PlayProgress && (
            <View style={styles.progressContent}>
              <View style={styles.descContent}>
                <Text style={styles.playProgressDesc}>
                  {computeTime(classRoomChangeTime / 1000)}
                </Text>
              </View>
              <Text style={styles.line}> / </Text>
              <View style={styles.rightDescContent}>
                <Text style={styles.totalTime}>
                  {computeTime(classRoomTotalTime / 1000)}
                </Text>
              </View>
            </View>
          )}

        {DEBUG &&
          currentPPT.type === PPTType.Video &&
          type !== ClassRoomType.Vod && (
            <Button
              text="下一环节"
              textStyle={styles.desc}
              style={styles.next}
              onPress={onPressNextRound}
            />
          )}
      </View>
    );
  }, [
    brightnessValue,
    classRoomChangeTime,
    classRoomTotalTime,
    currentPPT.type,
    responder.panHandlers,
    showPrepare,
    showToastType,
    type,
    volumeValue
  ]);
};
